#pragma once

#include "AST.h"
#include "SymbolTable.h"
#include <vector>
#include <string>

namespace MiniDB {

struct SemanticError {
    std::string error_type;
    int line;
    int column;
    std::string message;

    SemanticError(const std::string& type, int l, int c, const std::string& msg)
        : error_type(type), line(l), column(c), message(msg) {}
};

class SemanticAnalyzer {
public:
    explicit SemanticAnalyzer(SymbolTable& symbol_table);

    // 语义分析主函数
    bool analyze(const std::vector<std::shared_ptr<Statement>>& statements);

    // 单个语句分析
    bool analyzeStatement(std::shared_ptr<Statement> stmt);
    bool analyzeCreateTable(std::shared_ptr<CreateTableStatement> stmt);
    bool analyzeInsert(std::shared_ptr<InsertStatement> stmt);
    bool analyzeUpdate(std::shared_ptr<UpdateStatement> stmt);
    bool analyzeDelete(std::shared_ptr<DeleteStatement> stmt);
    bool analyzeSelect(std::shared_ptr<SelectStatement> stmt);

    // 表达式分析
    bool analyzeExpression(std::shared_ptr<Expression> expr, DataType& result_type);
    bool analyzeBinaryExpression(std::shared_ptr<BinaryExpression> expr, DataType& result_type);
    bool analyzeColumnReference(std::shared_ptr<ColumnReference> expr, DataType& result_type);
    bool analyzeLiteral(std::shared_ptr<Literal> expr, DataType& result_type);

    // 错误处理
    const std::vector<SemanticError>& getErrors() const { return errors_; }
    void clearErrors() { errors_.clear(); }
    bool hasErrors() const { return !errors_.empty(); }

    // 工具函数
    DataType stringToDataType(const std::string& type_str) const;
    std::string dataTypeToString(DataType type) const;

private:
    SymbolTable& symbol_table_;
    std::vector<SemanticError> errors_;

    void addError(const std::string& error_type, int line, int column, const std::string& message);
    bool checkTableExists(const std::string& table_name, int line, int column);
    bool checkColumnExists(const std::string& table_name, const std::string& column_name,
                          int line, int column, DataType& column_type);
};

} // namespace MiniDB
